package com.wan.server;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wan.entity.GameUser;
import com.wan.service.GameUserService;
import com.wan.util.ApplicationBeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Websocket Server websocket服务
 * @author XZX
 */
@Slf4j
@ServerEndpoint(value = "/bs/game/websocket/{userId}")
@Component
public class WebSocketServer {
    /**
     * 静态变量,用来记录当前连接数,应该是线程安全的
     */
    private static int onLineCount = 0;
    /**
     * concurrent包下线程安全的set,用来存放每个客户端对应的websocketserver
     */
    private static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
    /**
     * 与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    private Session session;
    /**接收userId*/
    private String userId="";
    /**
     * 新增spring上下文
     */

//    private RedisUtils redisUtils;
//
    private GameUserService gameUserService;
    /**
     * 建立连接调用的方法
     * @param session
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) throws IOException {
//        redisUtils = applicationContext.getBean(RedisUtils.class);
        gameUserService = ApplicationBeanUtil.getBean(GameUserService.class);
        this.session = session;
        this.userId=userId;
        if (webSocketMap.containsKey(userId)) {
            webSocketMap.remove(userId);
            webSocketMap.put(userId,this);
        }else {
            webSocketMap.put(userId,this);
            addOnLine();
        }
        GameUser user = gameUserService.getById(Integer.parseInt(userId));
        user.setStatus(1);
        gameUserService.updateById(user);
        sendMessage("连接成功,没有新消息");
        log.info("有新连接加入!当前连接数为:"+getLineCount());
        log.info("连接用户id:"+userId);
//        try {
//            String messageLists = "";
//            if (redisUtils.get(userId) != null){
//                messageLists = redisUtils.get(userId).toString();
//                sendMessage(messageLists);
//            }else {
//                //redis是null
//                QueryWrapper<StatusInfo> queryWrapper = new QueryWrapper<>();
//                queryWrapper.eq("user_id",userId);
//                queryWrapper.eq("status",0);
//                List<StatusInfo> statusInfos = statusInfoService.list(queryWrapper);
//                if (CollectionUtils.isEmpty(statusInfos)){
//                    sendMessage("连接成功,没有新消息");
//                }else {
//                    sendMessage(JSON.toJSONString(statusInfos));
//                }
//            }
//        }catch (IOException e){
//            log.error("websocket IO异常");
//        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if (webSocketMap.containsKey(userId)) {
            webSocketMap.remove(userId);
            subOnLineCount();
        }
        log.info("有一个连接关闭,当前连接数为:"+getLineCount());
    }

    /**
     * 客户端发送消息调用的方法
     * @param message
     * @throws IOException
     */
    @OnMessage
    public void onMessage(String message,Session session) throws IOException {
        log.info("来自客户端"+userId+"的消息:"+message);
        //可以群发消息
        //消息保存到数据库、redis
        if(StringUtils.isNotBlank(message)){
            try {
                //解析发送的报文
                JSONObject jsonObject = JSON.parseObject(message);
                //追加发送人(防止串改)
                jsonObject.put("fromUserId",this.userId);
                String toUserId=jsonObject.getString("toUserId");
                //传送给对应toUserId用户的websocket
                if(StringUtils.isNotBlank(toUserId)&&webSocketMap.containsKey(toUserId)){
                    webSocketMap.get(toUserId).sendMessage(jsonObject.toJSONString());
                }else{
                    log.error("请求的userId:"+toUserId+"不在该服务器上");
                    //否则不在这个服务器上，发送到mysql或者redis
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    /**
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }

    /**
     * 群发自定义消息
     * */
//    public static void sendInfo(String message)  {
//        log.info(message);
//        for (WebSocketServer item : socketServers) {
//            try {
//                item.sendMessage(message);
//            } catch (IOException e) {
//                continue;
//            }
//        }
//    }

    /**
     * 发送自定义消息
     * */
    public static void sendInfo(String message,@PathParam("userId") String userId) throws IOException {
        log.info("发送消息到:"+userId+"，报文:"+message);
        if(StringUtils.isNotBlank(userId)&&webSocketMap.containsKey(userId)){
            webSocketMap.get(userId).sendMessage(message);
        }else{
            log.error("用户"+userId+",不在线！");
        }
    }

    private static synchronized void subOnLineCount() {
        onLineCount--;
    }

    private void sendMessage(String string) throws IOException {
        this.session.getBasicRemote().sendText(string);
    }

    private static synchronized int getLineCount() {
        return onLineCount;
    }

    private static synchronized void addOnLine() {
        onLineCount++;
    }

}
